using NoodleShop.Api.HostedServices;
using NoodleShop.Api.Models;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace NoodleShop.Api.Controllers
{
    /// http://localhost:5000/api/orders
    [Route("api/[controller]")]
    [ApiController]
    public class OrdersController : ControllerBase
    {
        private readonly Kitchen _kitchen;

        public OrdersController(Kitchen kitchen)
        {
            _kitchen = kitchen;
        }

        [HttpPost]
        public IActionResult PlaceOrders(PlaceOrdersModel model)
        {
            List<OrderModel> result = ProcessOrdersInRealtime(model.Orders);
            return Ok(result);
        }

        private List<OrderModel> ProcessOrders(List<OrderModel> orders)
        {
            foreach (var order in orders)
            {
                ProcessOrder(order);
            }

            return orders;
        }

        private static void ProcessOrder(OrderModel order)
        {
            Thread.Sleep(500);
            order.Status = "Finished";
        }

        private List<OrderModel> ProcessOrdersInThreads(List<OrderModel> orders)
        {
            var threads = orders
                .Select(p => new Thread(() => ProcessOrder(p)))
                .ToArray();

            for (var i = 0; i < threads.Length; i++)
            {
                threads[i].Start();
            }

            for (var i = 0; i < threads.Length; i++)
            {
                threads[i].Join();
            }

            return orders;
        }

        private List<OrderModel> ProcessOrdersInTasks(List<OrderModel> orders)
        {
            var tasks = orders
                .Select(p => Task.Run(() => ProcessOrder(p)))
                .ToArray();

            Task.WaitAll(tasks);
            return orders;
        }

        private List<OrderModel> ProcessOrdersInRealtime(List<OrderModel> orders)
        {
            foreach (var order in orders)
            {
                order.Status = "Received";
                _kitchen.AddOrder(order);
            }

            return orders;
        }
    }
}
